﻿using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System.Collections.Generic;
using System;

namespace MyGames
{
    abstract class GameObject
    {
        #region Declarations
        protected Vector2 worldLocation;    // tọa độ thế giới
        protected Vector2 velocity;         // vận tốc

        protected bool enabled;             // object này có được hiển thị không 
        protected Color ogirinalColor = Color.White;
        protected Color affectColor = Color.White;

        protected float scale = 1f;         
        protected bool flipped = false;     // ???
        protected float drawDepth = 0.85f;  // độ sâu của object 

        protected Dictionary<string, AnimationStrip> animations = new Dictionary<string, AnimationStrip>();
        protected string currentAnimation;
        #endregion

        
        #region Properties
        public int FrameHeight
        {
            get { return (int)(animations[currentAnimation].FrameHeight * scale); }
        }

        public int FrameWidth
        {
            get { return (int)(animations[currentAnimation].FrameWidth * scale); }
        }

        public float Scale
        {
            get { return scale; }
            set { scale = value; }
        }

        public Color AffectColor
        {
            get { return affectColor; }
            set { affectColor = value; }
        }

        public bool Enabled
        {
            get { return enabled; }
            set { enabled = value; }
        }

        public Vector2 WorldLocation
        {
            get { return worldLocation; }
            set { worldLocation = value; }
        }

        public Vector2 WorldCenter
        {
            get
            {
                return new Vector2(worldLocation.X, worldLocation.Y - animations[currentAnimation].FrameHeight / 2); // ??? chua hieu
            }
        }

        public Rectangle WorldRectangle
        {
            get
            {
                return new Rectangle(
                    (int)(worldLocation.X - offset().X),
                    (int)(worldLocation.Y - offset().Y),
                    animations[currentAnimation].FrameWidth,
                    animations[currentAnimation].FrameHeight);
            }
        }

        public Rectangle CollisionRectangle
        {
            get
            {
                return new Rectangle(
                    (int)(worldLocation.X - scale * offset().X),
                    (int)(worldLocation.Y - scale * offset().Y),
                    (int)(scale * animations[currentAnimation].FrameWidth),
                    (int)(scale * animations[currentAnimation].FrameHeight));
            }
        }

        protected virtual Point offset()
        {
            return new Point(animations[currentAnimation].FrameWidth / 2, animations[currentAnimation].FrameHeight); // ???
        }
        #endregion

        #region Helper Methods
        private void updateAnimation(GameTime gameTime)
        {
            if (animations.ContainsKey(currentAnimation))
            {
                if (animations[currentAnimation].FinishedPlaying)
                {
                    PlayAnimation(animations[currentAnimation].NextAnimation);
                }
                else
                {
                    animations[currentAnimation].Update(gameTime);
                }
            }
        }
        #endregion

        #region Public Methods
        public void PlayAnimation(string name)
        {
            if (!(name == null) && animations.ContainsKey(name))
            {
                currentAnimation = name;
                animations[name].Play();
            }
        }

        public void PlayAnimation(string name, bool waitFinish, bool loop, bool reset)
        {
            if (reset || name != currentAnimation)
            {
                if (waitFinish && !animations[currentAnimation].FinishedPlaying)
                    return;

                currentAnimation = name;
                animations[currentAnimation].LoopAnimation = loop;
                animations[currentAnimation].Play();
            }
        }

        public bool IsCollideWith(GameObject obj, bool originLogic)
        {
            if (originLogic)
                return CollisionRectangle.Intersects(obj.CollisionRectangle) && Math.Abs(worldLocation.Y - obj.worldLocation.Y) <= 10;
            return CollisionRectangle.Intersects(obj.CollisionRectangle);
        }
        #endregion

        #region Update and Draw
        public virtual void Update(GameTime gameTime)
        {
            if (!enabled)
                return;

            float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds;
            updateAnimation(gameTime);

            Vector2 moveAmount = velocity * elapsed;
            Vector2 newPosition = worldLocation + moveAmount;
            newPosition = new Vector2(
                MathHelper.Clamp(newPosition.X, 0, Camera.WorldRectangle.Width),
                MathHelper.Clamp(newPosition.Y, 0, Camera.WorldRectangle.Height));
            worldLocation = newPosition;
        }

        public virtual void Draw(SpriteBatch spriteBatch)
        {
            if (!enabled)
                return;
            if (animations.ContainsKey(currentAnimation))
            {
                SpriteEffects effect = SpriteEffects.None;
                if (flipped)
                {
                    effect = SpriteEffects.FlipHorizontally;
                }

                Vector2 og = new Vector2(animations[currentAnimation].FrameWidth / 2, animations[currentAnimation].FrameHeight);
                spriteBatch.Draw(
                    animations[currentAnimation].Texture,
                    Camera.WorldToScreen(WorldLocation),
                    animations[currentAnimation].FrameRectangle,
                    affectColor, 0f, og, scale, effect, drawDepth);
            }
        }
        #endregion
    }
}

